package lab3;

import static org.junit.Assert.*;
import org.junit.Test;

/**
 * 习题类测试类（支持版本1.0和版本2.0） - 使用JUnit框架
 */
public class ExerciseTest {

    /**
     * 测试构造函数和基本属性
     */
    @Test
    public void testConstructor() {
        // 使用ArithmeticExpression对象构造（版本1.0）
        ArithmeticExpression expr = new ArithmeticExpression(5.0, 3.0, '+');
        Exercise exercise1 = new Exercise(expr);
        assertEquals(expr, exercise1.getExpression());
        assertFalse(exercise1.isAnswered());
        assertFalse(exercise1.isCorrect());
        assertNull(exercise1.getUserAnswer());
        
        // 使用操作数和运算符构造（版本1.0）
        Exercise exercise2 = new Exercise(10.0, 4.0, '-');
        assertEquals(10.0, exercise2.getExpression().getOperand1(), 0.001);
        assertEquals(4.0, exercise2.getExpression().getOperand2(), 0.001);
        assertEquals('-', exercise2.getExpression().getOperator());
    }
    
    /**
     * 测试使用抽象表达式构造（版本2.0）
     */
    @Test
    public void testAbstractExpressionConstructor() {
        // 使用AdditionExpression构造
        AbstractArithmeticExpression addExpr = new AdditionExpression(8.0, 5.0);
        Exercise exercise1 = new Exercise(addExpr);
        assertEquals(addExpr, exercise1.getAbstractExpression());
        assertNull(exercise1.getExpression()); // 版本2.0构造的习题expression字段应该为null
        assertFalse(exercise1.isAnswered());
        assertFalse(exercise1.isCorrect());
        assertEquals(13.0, exercise1.getCorrectAnswer(), 0.001);
        
        // 使用SubtractionExpression构造
        AbstractArithmeticExpression subExpr = new SubtractionExpression(10.0, 3.0);
        Exercise exercise2 = new Exercise(subExpr);
        assertEquals(subExpr, exercise2.getAbstractExpression());
        assertEquals(7.0, exercise2.getCorrectAnswer(), 0.001);
    }

    /**
     * 测试正确答案提交
     */
    @Test
    public void testCorrectAnswer() {
        // 版本1.0测试
        Exercise exercise = new Exercise(5.0, 3.0, '+');
        boolean result = exercise.submitAnswer(8.0);
        assertTrue(result);
        assertTrue(exercise.isAnswered());
        assertTrue(exercise.isCorrect());
        assertEquals(8.0, exercise.getUserAnswer(), 0.001);
        
        // 版本2.0测试 - 加法表达式
        AbstractArithmeticExpression addExpr = new AdditionExpression(12.0, 8.0);
        exercise = new Exercise(addExpr);
        result = exercise.submitAnswer(20.0);
        assertTrue(result);
        assertTrue(exercise.isAnswered());
        assertTrue(exercise.isCorrect());
        assertEquals(20.0, exercise.getUserAnswer(), 0.001);
        
        // 版本2.0测试 - 减法表达式
        AbstractArithmeticExpression subExpr = new SubtractionExpression(15.0, 7.0);
        exercise = new Exercise(subExpr);
        result = exercise.submitAnswer(8.0);
        assertTrue(result);
        assertTrue(exercise.isAnswered());
        assertTrue(exercise.isCorrect());
    }

    /**
     * 测试错误答案提交
     */
    @Test
    public void testIncorrectAnswer() {
        // 版本1.0测试
        Exercise exercise = new Exercise(5.0, 3.0, '+');
        boolean result = exercise.submitAnswer(7.0);
        assertFalse(result);
        assertTrue(exercise.isAnswered());
        assertFalse(exercise.isCorrect());
        assertEquals(7.0, exercise.getUserAnswer(), 0.001);
        
        // 版本2.0测试 - 加法表达式
        AbstractArithmeticExpression addExpr = new AdditionExpression(9.0, 4.0);
        exercise = new Exercise(addExpr);
        result = exercise.submitAnswer(12.0);  // 正确答案应为13.0
        assertFalse(result);
        assertTrue(exercise.isAnswered());
        assertFalse(exercise.isCorrect());
        assertEquals(12.0, exercise.getUserAnswer(), 0.001);
        
        // 版本2.0测试 - 减法表达式
        AbstractArithmeticExpression subExpr = new SubtractionExpression(20.0, 6.0);
        exercise = new Exercise(subExpr);
        result = exercise.submitAnswer(15.0);  // 正确答案应为14.0
        assertFalse(result);
        assertTrue(exercise.isAnswered());
        assertFalse(exercise.isCorrect());
    }

    /**
     * 测试浮点数精度处理
     */
    @Test
    public void testFloatingPointPrecision() {
        // 版本1.0测试
        Exercise exercise = new Exercise(1.0, 3.0, '/');
        // 0.333 应该被认为是正确的（接近1/3）
        boolean result = exercise.submitAnswer(0.333);
        assertTrue(result);
        assertTrue(exercise.isCorrect());
        
        // 版本2.0测试 - 加法表达式
        AbstractArithmeticExpression addExpr = new AdditionExpression(0.1, 0.2);
        exercise = new Exercise(addExpr);
        // 0.1 + 0.2 应该等于0.3，但由于浮点数精度问题可能略有偏差
        result = exercise.submitAnswer(0.3);
        assertTrue(result);
        assertTrue(exercise.isCorrect());
        
        // 版本2.0测试 - 减法表达式
        AbstractArithmeticExpression subExpr = new SubtractionExpression(1.0, 0.333);
        exercise = new Exercise(subExpr);
        // 1.0 - 0.333 = 0.667
        result = exercise.submitAnswer(0.667);
        assertTrue(result);
        assertTrue(exercise.isCorrect());
    }

    /**
     * 测试重置功能
     */
    @Test
    public void testReset() {
        // 版本1.0测试
        Exercise exercise = new Exercise(5.0, 3.0, '+');
        exercise.submitAnswer(8.0);
        assertTrue(exercise.isAnswered());
        
        exercise.reset();
        assertFalse(exercise.isAnswered());
        assertFalse(exercise.isCorrect());
        assertNull(exercise.getUserAnswer());
        
        // 版本2.0测试
        AbstractArithmeticExpression addExpr = new AdditionExpression(10.0, 7.0);
        exercise = new Exercise(addExpr);
        exercise.submitAnswer(17.0);
        assertTrue(exercise.isAnswered());
        assertTrue(exercise.isCorrect());
        
        exercise.reset();
        assertFalse(exercise.isAnswered());
        assertFalse(exercise.isCorrect());
        assertNull(exercise.getUserAnswer());
        // 确保重置不会丢失表达式对象
        assertEquals(addExpr, exercise.getAbstractExpression());
    }

    /**
     * 测试toString方法
     */
    @Test
    public void testToString() {
        // 版本1.0测试
        Exercise exercise = new Exercise(5.0, 3.0, '+');
        // 未回答时
        String str1 = exercise.toString();
        assertTrue(str1.contains("5.00 + 3.00"));
        assertFalse(str1.contains("用户答案"));
        
        // 回答正确时
        exercise.submitAnswer(8.0);
        String str2 = exercise.toString();
        assertTrue(str2.contains("用户答案"));
        assertTrue(str2.contains("结果: 正确"));
        
        // 回答错误时
        exercise.reset();
        exercise.submitAnswer(7.0);
        String str3 = exercise.toString();
        assertTrue(str3.contains("结果: 错误"));
        assertTrue(str3.contains("正确答案:"));
        
        // 版本2.0测试 - 加法表达式
        AbstractArithmeticExpression addExpr = new AdditionExpression(10.0, 5.0);
        exercise = new Exercise(addExpr);
        // 未回答时
        String str4 = exercise.toString();
        assertTrue(str4.contains("10.00 + 5.00"));
        
        // 回答正确时
        exercise.submitAnswer(15.0);
        String str5 = exercise.toString();
        assertTrue(str5.contains("用户答案"));
        assertTrue(str5.contains("结果: 正确"));
        
        // 版本2.0测试 - 减法表达式
        AbstractArithmeticExpression subExpr = new SubtractionExpression(20.0, 7.0);
        exercise = new Exercise(subExpr);
        // 回答错误时
        exercise.submitAnswer(12.0);
        String str6 = exercise.toString();
        assertTrue(str6.contains("结果: 错误"));
        assertTrue(str6.contains("正确答案:"));
        assertTrue(str6.contains("13.00")); // 正确答案应该是13.00
    }

    /**
     * 测试负数运算习题
     */
    @Test
    public void testNegativeNumberExercise() {
        // 版本1.0测试
        Exercise exercise = new Exercise(-5.0, 3.0, '+');
        double correctAnswer = exercise.getCorrectAnswer();
        assertEquals(-2.0, correctAnswer, 0.001);
        
        boolean result = exercise.submitAnswer(-2.0);
        assertTrue(result);
        assertTrue(exercise.isCorrect());
        
        // 版本2.0测试 - 加法表达式（负数+正数）
        AbstractArithmeticExpression addExpr = new AdditionExpression(-8.0, 5.0);
        exercise = new Exercise(addExpr);
        correctAnswer = exercise.getCorrectAnswer();
        assertEquals(-3.0, correctAnswer, 0.001);
        
        result = exercise.submitAnswer(-3.0);
        assertTrue(result);
        assertTrue(exercise.isCorrect());
        
        // 版本2.0测试 - 减法表达式（正数-负数）
        AbstractArithmeticExpression subExpr = new SubtractionExpression(10.0, -3.0);
        exercise = new Exercise(subExpr);
        correctAnswer = exercise.getCorrectAnswer();
        assertEquals(13.0, correctAnswer, 0.001);
        
        result = exercise.submitAnswer(13.0);
        assertTrue(result);
        assertTrue(exercise.isCorrect());
    }

    // JUnit测试类不需要main方法，通过JUnit运行器自动执行所有@Test注解的方法
}